Skip to content

Add prep-class-digest task for pre-class cohort gap synthesis#86

Merged
sgeinitz merged 3 commits into
mainfrom
prep-class-digest
May 9, 2026
Merged

Add prep-class-digest task for pre-class cohort gap synthesis#86
sgeinitz merged 3 commits into
mainfrom
prep-class-digest

Conversation

@sgeinitz

@sgeinitz sgeinitz commented May 7, 2026

Copy link
Copy Markdown
Owner

Summary

  • New prep-class-digest task: synthesizes a 1-page Markdown brief from recent quiz misses, follow-up reply themes, and media-recording transcripts in a configurable lookback window (default 7 days, override with --days N/-n N), ending with 2–3 in-class discussion questions targeted at the highest-priority gaps.
  • Local Gemma 4 handles all student-derived content (transcripts, criteria_evaluations, derived themes); an opt-in --cloud-questions/-q routes only the final question-drafting step to cloud Gemini 3 with a redacted prompt that contains only tag names + integer miss counts (no transcripts, no theme text).
  • New helper canvigator_utils.find_csvs_in_window (date-window companion to find_latest_csv) and a small refactor of canvigator.py's dispatch chain into a _run_course_task helper to keep complexity under flake8's max of 15.

Implementation notes

  • New module canvigator_digest.py orchestrates the pipeline in five phases: load (no LLM) → per-quiz follow-up theme summarization (Gemma 4) → per-recording analysis (reuses existing analyze_recording_tags + extract_recording_themes) → discussion-question synthesis (Gemma 4 default, Gemini 3 opt-in) → render to Markdown.
  • The split between local and cloud paths is enforced at the prompt-builder level: _buildDiscussionPromptLocal embeds derived theme bullets, while _buildDiscussionPromptCloud only embeds tag strings and counts.
  • Empty-window guardrail: if no quiz/follow-up/recording activity is found in the lookback period, the task short-circuits with a friendly message and writes no file. Same-day re-runs overwrite (matches analysis_YYYYMMDD.md precedent).

Tests

  • 29 new tests across 9 TestX classes covering: window CSV discovery, quiz-miss tallying, follow-up assessment loading + NaT handling, prompt builders (explain + draw modes, row cap), priority ranking across all three signal sources, model selection, render section ordering, and the empty-window orchestrator path.
  • Privacy guardrail test (TestBuildDiscussionPromptCloud): asserts that synthetic transcripts and criteria_evaluations content cannot leak into the redacted cloud prompt.
  • 264/264 tests pass; both flake8 commands clean.

Test plan

  • Run python canvigator.py --crn <CRN> prep-class-digest against a real course directory with prior data; verify data/<course>/class_digest_YYYYMMDD.md is written with all five sections.
  • Verify the discussion-questions section came from the local model (check log line: model=gemma4:31b host=localhost).
  • Run python canvigator.py --crn <CRN> --days 14 --cloud-questions prep-class-digest; verify log shows model=gemini-3-flash-preview host=ollama.com prompt_variant=cloud.
  • Empty-window guardrail: run against a course directory with no recent activity; verify the friendly no-op message and that no output file is created.
  • All-pass cohort guardrail: in a course with no failed follow-ups, verify the discussion-questions section renders the no-gaps string with no LLM call.

🤖 Generated with Claude Code

Synthesizes a 1-page Markdown brief from recent quiz misses, follow-up reply
themes, and media-recording transcripts in a configurable lookback window
(default 7 days), ending with 2-3 in-class discussion questions targeted at
the highest-priority gaps. Local Gemma 4 handles all student-derived content;
an opt-in --cloud-questions routes only the final question-drafting step to
cloud Gemini 3 with a redacted prompt that contains tag names + miss counts
but no transcripts or theme text.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8480bbb974

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread canvigator_digest.py
signal (in which case nothing is written).
"""
today = datetime.now(timezone.utc).date()
since_date = today - timedelta(days=days)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Subtract one day when computing lookback start

The lookback window currently starts at today - timedelta(days=days) while downstream loaders include files/rows with >= since_date, so --days 7 actually spans 8 calendar dates (today plus 7 prior days). This causes the digest to pull older quiz/follow-up/recording signals than requested and can skew the ranked gaps whenever there is activity exactly one day beyond the intended window.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@codex Can you take another look at these two new commits also?

sgeinitz and others added 2 commits May 8, 2026 12:49
The -a/--all flag has worked with send-quiz-reminder for a while but the
task-level help description and the README's send-quiz-reminder section
didn't mention it, so users had to read the global flag description (or
CLAUDE.md) to discover it.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
`canvigator.py <task> --help` (and `-h`) now renders a focused
per-task cheat-sheet: description, prerequisites, file inputs/outputs,
applicable flags, example invocations, and a Workflow line listing
related tasks to run before/after. Addresses the growing pain of
keeping 22 tasks, their dependencies, and their I/O straight.

Per-task data lives in a new `canvigator_help.py` module so the CLI
file doesn't grow with every task. `FLAG_DESCRIPTIONS` is the single
source for flag wording — both the global and per-task renderers
share it. The existing global `--help` continues to work; a new
footer points users at the per-task form.

Tests in `TestPerTaskHelp` cover integrity (every task has an entry,
required fields non-empty, flag references resolve, run_before/after
targets exist), rendering, and end-to-end CLI dispatch via subprocess.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f417cda164

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread canvigator_digest.py
signal (in which case nothing is written).
"""
today = datetime.now(timezone.utc).date()
since_date = today - timedelta(days=days)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Compute digest cutoff as an N-day inclusive window

prepClassDigest currently sets since_date = today - timedelta(days=days) and downstream loaders include rows where the date is >= since_date, which makes --days 7 include 8 calendar days (today plus 7 prior days). This inflates miss/theme counts with one extra day of older data whenever users rely on the documented “last N days” window. Use an inclusive cutoff of today - timedelta(days=days-1) (or keep current cutoff and switch comparisons to >).

Useful? React with 👍 / 👎.

@sgeinitz sgeinitz merged commit c5d8add into main May 9, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant